package app.server.project.main.service.service.recharge;

import app.server.project.core.constants.Def;
import app.server.project.core.constants.TcpCmd;
import app.server.project.core.util.GlobalValChangeEvent;
import app.server.project.core.websocket.WSMgr;
import app.server.project.main.service.bo.event.CreateLuckOrderEvent;
import app.server.project.main.service.bo.event.RechargeSuccessEvent;
import app.server.project.main.service.constants.GlobalCfgKey;
import app.server.project.main.service.constants.LuckType;
import app.server.project.main.service.db.dao.cfg.GlobalCfgDao;
import app.server.project.main.service.db.dao.cfg.RechargeCfgDao;
import app.server.project.main.service.db.dao.user.RechargeOrderDao;
import app.server.project.main.service.dto.recharge.BuyStarReq;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.pengrad.telegrambot.Callback;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.UpdatesListener;
import com.pengrad.telegrambot.model.MenuButtonWebApp;
import com.pengrad.telegrambot.model.Message;
import com.pengrad.telegrambot.model.SuccessfulPayment;
import com.pengrad.telegrambot.model.WebAppInfo;
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
import com.pengrad.telegrambot.model.request.LabeledPrice;
import com.pengrad.telegrambot.model.request.ParseMode;
import com.pengrad.telegrambot.request.AnswerPreCheckoutQuery;
import com.pengrad.telegrambot.request.CreateInvoiceLink;
import com.pengrad.telegrambot.request.SendPhoto;
import com.pengrad.telegrambot.request.SetChatMenuButton;
import com.pengrad.telegrambot.response.BaseResponse;
import com.pengrad.telegrambot.response.StringResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.Objects;

@RequiredArgsConstructor
@Slf4j
@Service
public class StarRecharge {

    private final static String START = "/start";


    private final RechargeCfgDao rechargeCfgDao;

    private final GlobalCfgDao globalCfgDao;

    private final RechargeOrderDao rechargeOrderDao;
    private final ApplicationEventPublisher applicationEventPublisher;
    private TelegramBot telegramBot;


    @Async(Def.CommonPool)
    public void buy(BuyStarReq req, long userId) {


        var cfg = this.rechargeCfgDao.getDataById(req.getRechargeId());
        //创建订单
        var orderId = IdUtil.getSnowflakeNextId();
        var order = this.rechargeOrderDao.getOneByOrderId(orderId);
        order.setSynDb(true);
        order.setCreateTime(new Date());
        order.setUserId(userId);
        order.setPayType(RechargeType.Star);
        if (req.getConsumeNum() > Def.Zero) {
            order.setConsumeNum(req.getConsumeNum());
        } else {
            order.setConsumeNum(cfg.getConsumeNum());
        }

        order.setRechargeCfgId(req.getRechargeId());
        order.setStatus(PayStatus.Wait);

        //开始拉起tg star支付
        CreateInvoiceLink sendInvoice = new CreateInvoiceLink(
                cfg.getStarTitle(),
                cfg.getStarDes(),
                String.valueOf(orderId),
                "XTR",
                new LabeledPrice(String.format("%s star", (int) order.getConsumeNum()), (int) order.getConsumeNum())
        );

        var ret = this.telegramBot.execute(sendInvoice, new Callback<CreateInvoiceLink, StringResponse>() {
            @Override
            public void onResponse(CreateInvoiceLink createInvoiceLink, StringResponse stringResponse) {
                log.info("下单成功:{}:===={}", stringResponse, stringResponse.result());
                if (stringResponse.isOk()) {
                    WSMgr.push(userId, TcpCmd.Star, stringResponse.result());

                    //判断是否是抽奖
                    if (StrUtil.isNotBlank(req.getChoice())) {
                        if (req.getOrderType() == LuckType.BTC) {
                            if (req.getChoice().length() != 4) {
                                return;
                            }
                        }
                        if (req.getOrderType() == LuckType.SOL) {
                            if (req.getChoice().length() != 1) {
                                return;
                            }
                        }
                        applicationEventPublisher.publishEvent(CreateLuckOrderEvent.of(userId, req.getChoice(), orderId, req.getOrderType()));
                    }
                }

            }

            @Override
            public void onFailure(CreateInvoiceLink createInvoiceLink, IOException e) {

            }
        });

    }


    public void sendMsg(String url, String msg, long userId) {
        try {
            SendPhoto sendPhoto = new SendPhoto(userId, url)
                    .parseMode(ParseMode.HTML)
                    .caption(msg);
            var response = this.telegramBot.execute(sendPhoto);
            //log.info("发送消息成功:{}", response);
        } catch (Exception e) {
            //log.error("发送消息失败", e);
        }

    }


    private void doWelComeMsg(Message message) {

        String title = this.globalCfgDao.getStr(GlobalCfgKey.TG_LOAD_TITLE);
        String url = this.globalCfgDao.getStr(GlobalCfgKey.TG_GAME_URL);
        String xUrl = this.globalCfgDao.getStr(GlobalCfgKey.BOT_X);
        String tg = this.globalCfgDao.getStr(GlobalCfgKey.BOT_TG);

        InlineKeyboardMarkup inlineKeyboard = new InlineKeyboardMarkup(
                new InlineKeyboardButton[]{
                        new InlineKeyboardButton(title)
                                .webApp(new WebAppInfo(url)
                        ),
                },
                new InlineKeyboardButton[]{
                        new InlineKeyboardButton("\uD83D\uDC26 Follow X")
                                .url(xUrl),
                        new InlineKeyboardButton("\uD83E\uDDD1\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1 Join TG group").url(tg),
                }
        );

        SendPhoto sendPhoto = new SendPhoto(message.from().id(),
                this.globalCfgDao.getStr(GlobalCfgKey.TG_GAME_PHOTO))
                .parseMode(ParseMode.HTML)
                .caption(this.globalCfgDao.getStr(GlobalCfgKey.TG_GAME_WEL))
                .replyMarkup(inlineKeyboard);
        var response = this.telegramBot.execute(sendPhoto);

    }


    @EventListener(classes = {ApplicationReadyEvent.class, GlobalValChangeEvent.class})
    public void initHttpTGAPI() {
        String botToken = this.globalCfgDao.getOneByKey(GlobalCfgKey.BOT_TOKEN).getVal();
        this.telegramBot = new TelegramBot(botToken);
        //初始化菜单
        SetChatMenuButton setChatMenuButton = new SetChatMenuButton();
        MenuButtonWebApp menuButtonWebApp = new MenuButtonWebApp(
                this.globalCfgDao.getStr(GlobalCfgKey.TG_LOAD_TITLE),
                new WebAppInfo(this.globalCfgDao.getStr(GlobalCfgKey.TG_GAME_URL)));
        setChatMenuButton.menuButton(menuButtonWebApp);
        this.telegramBot.execute(setChatMenuButton, new Callback<SetChatMenuButton, BaseResponse>() {
            @Override
            public void onResponse(SetChatMenuButton setChatMenuButton, BaseResponse baseResponse) {

            }

            @Override
            public void onFailure(SetChatMenuButton setChatMenuButton, IOException e) {

            }
        });
        //初始化监听
        this.telegramBot.setUpdatesListener((v) -> {

            try {
                v.forEach(u -> {
                    if (Objects.nonNull(u.preCheckoutQuery())) {
                        var preCheckoutQuery = u.preCheckoutQuery();
                        AnswerPreCheckoutQuery answerCheckout = new AnswerPreCheckoutQuery(preCheckoutQuery.id());
                        BaseResponse response = this.telegramBot.execute(answerCheckout);
                        //log.info("批准下单:{}", response);
                    } else {
                        if (Objects.nonNull(u.message())) {
                            if (StrUtil.isNotBlank(u.message().text()) && START.equals(u.message().text())) {
                                //处理欢迎消息
                                this.doWelComeMsg(u.message());
                            } else {
                                //log.info("进入支付{}", v);
                                //处理订单消息
                                if (Objects.nonNull(u.message().successfulPayment())) {
                                    SuccessfulPayment successfulPayment = u.message().successfulPayment();
                                    log.info("star 订单号:{} 订单成功支付回调:{}", successfulPayment.invoicePayload(), successfulPayment);
                                    //开始检查订单状态
                                    var order = this.rechargeOrderDao.getOneByOrderId(Long.parseLong(successfulPayment.invoicePayload()));
                                    if (order.getUserId() > Def.Zero && successfulPayment.totalAmount() >= order.getConsumeNum()) {
                                        order.setStatus(PayStatus.Finish);
                                        var cfg = this.rechargeCfgDao.getDataById(order.getRechargeCfgId());
                                        this.applicationEventPublisher.publishEvent(RechargeSuccessEvent.create(order.getUserId(), cfg, order));
                                    }
                                }
                            }
                        }
                    }

                });
            } catch (Exception e) {
                //log.error("bot 消息 处理支付异常====", e);
            }

            return UpdatesListener.CONFIRMED_UPDATES_ALL;
        }, (e) -> {
            //log.error("bot 消息错误====", e);
        });
    }

}
